package cn.shadow.client;

import cn.shadow.message.WorkerFactory;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldPrepender;
import lombok.Data;

@Data
public class NettyClient {

    private EventLoopGroup eventExecutors;
    private Bootstrap bootstrap;
    private final String IP;
    private final int port;
    WorkerFactory workerFactory;

    NettyClient(String Ip, int port, WorkerFactory workerFactory) {
        this.IP = Ip;
        this.port = port;
        this.workerFactory = workerFactory;
        eventExecutors = new NioEventLoopGroup();
    }

    public void config() {
        bootstrap = new Bootstrap();
        bootstrap.group(eventExecutors)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() { //设置处理数据的handler
                    @Override
                    protected void initChannel(SocketChannel sc) throws Exception {
                        ChannelPipeline pipeline = sc.pipeline();
                        pipeline.addLast(new SingleDecodeHandler(workerFactory));
                        pipeline.addLast(new LengthFieldPrepender(4)); //将要发的消息长度计算好，加到消息里面去
                        pipeline.addLast(new NettyClientHandler());
                    }
                });
        System.out.println("客户端准备好了");
    }

    public void start() {

        ChannelFuture channelFuture = bootstrap.connect(IP, port).addListener(f -> {
            if (f.isSuccess()) {
                System.out.println("连接成功");
            }
        });
        //对关闭通道进行监听
        channelFuture.channel().closeFuture().addListener(future -> {
            if (future.isSuccess()) {
                close();
            }
        });
    }


    public void close() {
        eventExecutors.shutdownGracefully();
    }
}
